package little_david.finderlibrary;

import android.app.Activity;
import android.support.annotation.NonNull;
import android.support.v4.app.Fragment;
import android.view.View;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

import little_david.finderlibrary.finder_annotation.BindView;
import little_david.finderlibrary.finder_annotation.ClickEvent;

public class Finder {

    private Finder() throws Exception {
        throw new Exception("Invalidate constructor");
    }


    /**
     * 用于存储所有的已经绑定的对象的集合
     */
    static Map<Unbinder, View> Pot = new HashMap<>();


    /**
     * 用于绑定活动
     */
    public static Unbinder bind(@NonNull Activity target) {
        Unbinder unbinder = new Unbinder(target);
        Pot.put(unbinder, target.getWindow().getDecorView());
        apply(unbinder);
        return unbinder;
    }

    /**
     * 用于绑定碎片
     */
    public static Unbinder bind(Fragment target) {
        Unbinder unbinder = new Unbinder(target);
        Pot.put(unbinder, target.getView());
        apply(unbinder);
        return unbinder;
    }


    private static void apply(Unbinder unbinder) {
        try {
            //视图对象
            View view = Pot.get(unbinder);
            bindView(unbinder.holder, view);
            bindMethod(unbinder.holder, view);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 绑定View，为标记的字段
     */
    private static void bindView(Object holder, View view) throws Exception {
        Class cls = holder.getClass();

        Field[] fields = cls.getFields();
        for (Field field : fields) {
            //过滤没有被@BindView标记的字段
            if (!field.isAnnotationPresent(BindView.class))
                continue;
            //获取我们注解的详细的对象，并赋值
            BindView bindView = field.getAnnotation(BindView.class);
            int viewResId = bindView.value();
            View targetView = view.findViewById(viewResId);
            field.set(holder, targetView);
        }
    }

    /**
     * 绑定OnClick方法
     */
    private static void bindMethod(Object holder, View view) throws Exception {
        Class cls = holder.getClass();
        Method[] methods = cls.getMethods();
        for (Method method : methods) {
            //过滤没有被注解的方法
            if (!method.isAnnotationPresent(ClickEvent.class))
                continue;

            Class[] parameterClsArray = method.getParameterTypes();

            //过滤被注解了但是不合法的方法
            if (parameterClsArray.length != 1 || parameterClsArray[0] != View.class)
                continue;

            //绑定点击事件
            ClickEvent event = method.getAnnotation(ClickEvent.class);
            for (int resId : event.value()) {
                View eventView = view.findViewById(resId);
                bindOnClickListener(holder, eventView, method);
            }
        }
    }

    /**
     * 为View绑定ONClick事件
     */
    private static void bindOnClickListener(final Object holder, View view, final Method method) {
        view.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                try {
                    method.invoke(holder, v);
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    e.printStackTrace();
                }
            }
        });
    }

    /**
     * 从集合释放掉占用的对象
     */
    public static void unbind(Unbinder unbinder) {
        unbinder.holder = null;
        Pot.remove(unbinder);
    }

}
